package day01;

/**
 * @author aiPlusPlus
 * @version 1.0
 * @date 2023/3/1 18:23
 */

import java.util.LinkedList;

/**
 * 给你一个大小为 n x n 的整数矩阵 grid 。
 *
 * 生成一个大小为 (n - 2) x (n - 2) 的整数矩阵  maxLocal ，并满足：
 *
 * maxLocal[i][j] 等于 grid 中以 i + 1 行和 j + 1 列为中心的 3 x 3 矩阵中的 最大值 。
 * 换句话说，我们希望找出 grid 中每个 3 x 3 矩阵中的最大值。
 *
 * 返回生成的矩阵。
 *
 *
 *
 * 示例 1：
 *
 *
 *
 * 输入：grid = [[9,9,8,1],[5,6,2,6],[8,2,6,4],[6,2,2,2]]
 * 输出：[[9,9],[8,6]]
 * 解释：原矩阵和生成的矩阵如上图所示。
 * 注意，生成的矩阵中，每个值都对应 grid 中一个相接的 3 x 3 矩阵的最大值。
 * 示例 2：
 *
 *
 *
 * 输入：grid = [[1,1,1,1,1],[1,1,1,1,1],[1,1,2,1,1],[1,1,1,1,1],[1,1,1,1,1]]
 * 输出：[[2,2,2],[2,2,2],[2,2,2]]
 * 解释：注意，2 包含在 grid 中每个 3 x 3 的矩阵中。
 */
public class Solution1 {
    public int[][] largestLocal(int[][] grid) {
        int n = grid.length;
        int[][] res = new int[n - 2][n - 2];    // 创建结果数组
        LinkedList<Integer> queue;  // 单调队列
        int value;
        for(int i = 0; i < n; i++){
            queue = new LinkedList<>(); // 每一行新建一个单调队列
            for(int j = 0; j < n; j++){
                // 单调队列添加候选值
                while(!queue.isEmpty() && grid[i][j] >= grid[i][queue.peekLast()]){
                    queue.pollLast();
                }
                queue.offerLast(j);
                //滑动窗口达到大小3可以处理
                if(j >= 2){
                    value = grid[i][queue.peekFirst()]; // 获取单调队列中当前行当前滑动窗口中的最大值 即队首索引对应的值
                    for(int k = i - 2; k <= i; k++){    // 更新当前行及其前两行该列的最大值
                        if(k >= 0 && k < n - 2){    // 行必须在结果数组的范围内
                            res[k][j - 2] = Math.max(res[k][j - 2],value);
                        }
                    }
                    if(queue.peekFirst() <= j - 2){ // 当前最大值位于滑动窗口最左侧，弹出这个最大值
                        queue.pollFirst();
                    }
                }
            }
        }
        return res;
    }
}
